
import { Node, v3, Vec3, __private } from 'cc';

/**
 * 节点回收模式
 * @date 2022/3/21 - 上午10:28:16
 *
 * @export
 * @enum {number}
 */
export enum NodeRecycleMode {
    /**通过节点的Active属性来回收*/
    Active = "Active",
    /**设置固定位置和缩放的方式来回收(设置一个很远)*/
    SetFixedPositionAndScale = "SetFixedPositionAndScale",
}
/**实现节点的回收器*/
export interface INodeRecoverer {
    recycle(node: Node): void;
    reuse(node: Node): void;
}

/**激活方式的回收器*/
export class ActiveNodeRecoverer implements INodeRecoverer {
    recycle(node: Node): void {
        node.active = false;
    }
    reuse(node: Node): void {
        node.active = true;
    }
}

interface SetFixedPositionAndScaleRawData {
    rawPosition: Vec3;
    rawScale: Vec3;
}
/**设置固定位置和缩放的回收器*/
export class SetFixedPositionAndScaleNodeRecoverer implements INodeRecoverer {
    private nodeRawData: Map<string, SetFixedPositionAndScaleRawData> = new Map<string, SetFixedPositionAndScaleRawData>();

    public fixedPosition: Vec3;
    public fixedScale: Vec3;
    constructor(fixedPosition: Vec3, fixedScale: Vec3) {
        this.fixedPosition = fixedPosition;
        this.fixedScale = fixedScale;
    }

    initRaw(node: Node): SetFixedPositionAndScaleRawData {
        var rawData: SetFixedPositionAndScaleRawData = {
            rawPosition: v3(node.position.x, node.position.y, node.position.z),
            rawScale: v3(node.scale.x, node.scale.y, node.scale.z),
        };
        this.nodeRawData.set(node.uuid, rawData);
        return rawData;
    }
    recycle(node: Node): void {
        var d = this.nodeRawData.get(node.uuid);
        if (!d) {
            d = this.initRaw(node);
        } else {
            d.rawPosition.set(node.position);
            d.rawScale.set(node.scale);
        }
        node.position.set(this.fixedPosition);
        node.scale.set(this.fixedScale);
    }
    reuse(node: Node): void {
        var d = this.nodeRawData.get(node.uuid);
        if (!d) return;
        node.position.set(d.rawPosition);
        node.scale.set(d.rawScale);
    }
}

/**节点池*/
export class NodeRecyclePool {
    private nodeRecoverer: INodeRecoverer;
    private nodeStorage: Node[] = [];
    
    /**
     * 使用激活模式构造节点回收池
     * @date 2022/3/21 - 下午1:52:03
     *
     * @constructor
     * @param {NodeRecycleMode.Active} mode
     */
    constructor(mode: NodeRecycleMode.Active);
    
    /**
     * 使用设置固定位置和缩放的模式构造节点回收池
     * @date 2022/3/21 - 下午1:52:44
     *
     * @constructor
     * @param {NodeRecycleMode.SetFixedPositionAndScale} mode
     * @param {Vec3} fixedPosition 回收时需要设置到的本地坐标
     * @param {Vec3} fixedScale 回收时需要设置的本地缩放
     */
    constructor(mode: NodeRecycleMode.SetFixedPositionAndScale, fixedPosition: Vec3, fixedScale: Vec3);
    constructor(mode: NodeRecycleMode, fixedPosition?: Vec3, fixedScale?: Vec3) {
        switch (mode) {
            case NodeRecycleMode.Active:
                this.nodeRecoverer = new ActiveNodeRecoverer();
                break;
            case NodeRecycleMode.SetFixedPositionAndScale:
                this.nodeRecoverer = new SetFixedPositionAndScaleNodeRecoverer(fixedPosition!, fixedScale!);
                break;
        }
    }

    public reuseOne(): Node | null {
        if (this.nodeStorage.length <= 0) return null;
        var node = this.nodeStorage.shift();
        if(!node)return null;
        this.nodeRecoverer.reuse(node);
        return node;
    }

    public recycle(node: Node){
        this.nodeRecoverer.recycle(node);
        this.nodeStorage.push(node);
    }

}
